package com.smart.community.property.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.property.dto.RepairOrderDTO;
import com.smart.community.property.service.DataScopeService;
import com.smart.community.property.service.IPropertyService;
import com.smart.community.property.service.IRepairOrderService;
import com.smart.community.property.vo.RepairOrderVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

/**
 * 移动端维修工单管理控制器
 * 
 * 严格按照《Java后端SpringBoot代码开发规范.md》权威标准实现：
 * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
 * - 移除Controller层log.error：避免日志级别错误
 * - 详细的日志记录，包括开始、成功状态
 * - 统一的返回格式，提供用户友好的错误提示
 * - 完善的权限验证和业务逻辑验证
 * - 完整的JavaDoc注释和Swagger文档
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/property/repair-orders")
@Tag(name = "移动端维修工单管理", description = "移动端维修工单的查询、分配、处理等接口")
public class RepairOrderMobileController {

    @Autowired
    private IRepairOrderService repairOrderService;
    
    @Autowired
    private DataScopeService dataScopeService;
    
    @Autowired
    private IPropertyService propertyService;

    /**
     * 获取维修工单统计概览
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 使用SecurityUtils.getCurrentUserId()获取当前用户ID
     * - 进行完整的权限验证
     * 
     * @return 统计概览信息
     * @throws Exception 统一异常
     */
    @GetMapping("/mobile/statistics")
    @Operation(summary = "获取维修工单统计概览", description = "移动端获取维修工单统计概览信息")
    public Result<Map<String, Object>> getRepairOrderStatistics() throws Exception {
        // 用户登录状态检查
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("获取维修工单统计概览失败，用户未登录");
            return Result.fail("用户未登录");
        }
        
        // 获取用户数据权限信息
        DataScopeInfo dataScopeInfo = dataScopeService.getCurrentUserDataScope();
        if (dataScopeInfo == null) {
            log.warn("获取维修工单统计概览失败，用户数据权限信息为空，用户ID: {}", userId);
            return Result.fail("用户权限信息获取失败");
        }
        
        // 获取用户关联的社区ID列表
        List<Long> communityIds = dataScopeInfo.getCommunityIds();
        if (communityIds == null || communityIds.isEmpty()) {
            log.warn("获取维修工单统计概览失败，用户无关联社区，用户ID: {}", userId);
            return Result.fail("用户无关联社区");
        }
        
        // 调用Service层获取统计信息
        Map<String, Object> statistics = repairOrderService.getMobileRepairOrderStatistics(userId, communityIds);
        return Result.success("查询成功", statistics);
    }

    /**
     * 获取待分配工单列表
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 使用SecurityUtils.getCurrentUserId()获取当前用户ID
     * - 根据物业公司获取社区ID，筛选状态为1的工单
     * 
     * @param current 当前页
     * @param size 每页大小
     * @return 待分配工单列表
     * @throws Exception 统一异常
     */
    @GetMapping("/mobile/pending-assignment")
    @Operation(summary = "获取待分配工单列表", description = "移动端获取待分配工单列表，根据物业公司获取社区ID，筛选状态为1的工单")
    public Result<Map<String, Object>> getPendingAssignmentOrders(
            @Parameter(description = "当前页") @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer size) throws Exception {
        // 用户登录状态检查
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("获取待分配工单列表失败，用户未登录");
            return Result.fail("用户未登录");
        }
        
        // 分页参数验证
        if (current == null || current < 1) {
            current = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }
        
        // 获取用户数据权限信息
        DataScopeInfo dataScopeInfo = dataScopeService.getCurrentUserDataScope();
        if (dataScopeInfo == null) {
            log.warn("获取待分配工单列表失败，用户数据权限信息为空，用户ID: {}", userId);
            return Result.fail("用户权限信息获取失败");
        }
        
        // 获取用户关联的社区ID列表
        List<Long> communityIds = dataScopeInfo.getCommunityIds();
        if (communityIds == null || communityIds.isEmpty()) {
            log.warn("获取待分配工单列表失败，用户无关联社区，用户ID: {}", userId);
            return Result.fail("用户无关联社区");
        }
        
        // 调用Service层获取待分配工单列表
        Map<String, Object> result = repairOrderService.getPendingAssignmentOrders(current, size, communityIds);
        return Result.success("查询成功", result);
    }





    /**
     * 获取我的工单列表（维修人员）
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 使用SecurityUtils.getCurrentUserId()获取当前用户ID
     * - 根据当前用户获取分配给该用户的工单列表
     * 
     * @param current 当前页
     * @param size 每页大小
     * @param status 工单状态（可选）
     * @return 我的工单列表
     * @throws Exception 统一异常
     */
    @GetMapping("/mobile/my-assigned-orders")
    @Operation(summary = "获取我的工单列表（维修人员）", description = "移动端获取分配给当前用户的工单列表")
    public Result<Map<String, Object>> getMyAssignedOrders(
            @Parameter(description = "当前页") @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "工单状态") @RequestParam(required = false) Integer status) throws Exception {
        // 用户登录状态检查
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("获取我的工单列表失败，用户未登录");
            return Result.fail("用户未登录");
        }
        
        // 分页参数验证
        if (current == null || current < 1) {
            current = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }
        
        log.info("开始获取我的工单列表，用户ID: {}, 状态: {}, 当前页: {}, 每页大小: {}", userId, status, current, size);
        
        // 调用Service层获取我的工单列表
        Map<String, Object> result = repairOrderService.getMyOrders(userId, current, size, status);
        
        log.info("获取我的工单列表成功，用户ID: {}, 总记录数: {}, 当前页记录数: {}", 
                userId, result.get("total"), result.get("records"));
        return Result.success("查询成功", result);
    }

    /**
     * 获取用户数据权限信息（包含物业公司和社区ID）
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 使用SecurityUtils.getCurrentUserId()获取当前用户ID
     * - 返回用户权限信息供移动端缓存
     * 
     * @return 用户数据权限信息
     * @throws Exception 统一异常
     */
    @GetMapping("/mobile/user-permission-info")
    @Operation(summary = "获取用户数据权限信息", description = "移动端获取用户数据权限信息，包含物业公司和社区ID，供移动端缓存")
    public Result<Map<String, Object>> getUserPermissionInfo() throws Exception {
        // 用户登录状态检查
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("获取用户数据权限信息失败，用户未登录");
            return Result.fail("用户未登录");
        }
        
        // 获取用户数据权限信息
        DataScopeInfo dataScopeInfo = dataScopeService.getCurrentUserDataScope();
        if (dataScopeInfo == null) {
            log.warn("获取用户数据权限信息失败，用户数据权限信息为空，用户ID: {}", userId);
            return Result.fail("用户权限信息获取失败");
        }
        
        // 构建返回信息
        Map<String, Object> permissionInfo = new HashMap<>();
        permissionInfo.put("userId", userId);
        permissionInfo.put("isSuperAdmin", dataScopeInfo.isSuperAdmin());
        permissionInfo.put("isPropertyCompanyUser", dataScopeInfo.isPropertyCompanyUser());
        permissionInfo.put("isOwnerUser", dataScopeInfo.isOwnerUser());
        permissionInfo.put("propertyCompanyIds", dataScopeInfo.getPropertyCompanyIds());
        permissionInfo.put("communityIds", dataScopeInfo.getCommunityIds());
        permissionInfo.put("scopeDescription", dataScopeInfo.getScopeDescription());
        return Result.success("查询成功", permissionInfo);
    }

    /**
     * 移动端用户报修
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 使用SecurityUtils.getCurrentUserId()获取当前用户ID
     * - 进行完整的权限验证和参数验证
     * 
     * @param repairOrderDTO 维修工单DTO
     * @return 提交结果
     * @throws Exception 统一异常
     */
    @PostMapping("/mobile/submit")
    @Operation(summary = "移动端用户报修", description = "移动端用户提交报修申请，支持图片上传")
    public Result<Long> mobileSubmitRepairOrder(@RequestBody RepairOrderDTO repairOrderDTO) throws Exception {
        // 用户登录状态检查
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("移动端用户报修失败，用户未登录");
            return Result.fail("用户未登录，请先登录");
        }
        
        // 参数基础验证
        if (repairOrderDTO == null) {
            log.warn("移动端用户报修失败，请求参数为空，用户ID: {}", userId);
            return Result.fail("请求参数不能为空");
        }
        
        // 设置当前用户ID
        repairOrderDTO.setUserId(userId);
        
        // 手动验证DTO
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<RepairOrderDTO>> violations = validator.validate(repairOrderDTO);
        if (!violations.isEmpty()) {
            StringBuilder errorMsg = new StringBuilder();
            for (ConstraintViolation<RepairOrderDTO> violation : violations) {
                errorMsg.append(violation.getPropertyPath()).append(": ").append(violation.getMessage()).append("; ");
            }
            log.warn("移动端用户报修参数验证失败，用户ID: {}, 错误信息: {}", userId, errorMsg.toString());
            return Result.fail("参数验证失败: " + errorMsg.toString());
        }
        
        // 图片列表验证
        if (repairOrderDTO.getImageList() != null && repairOrderDTO.getImageList().size() > 9) {
            log.warn("移动端用户报修图片数量超限，用户ID: {}, 图片数量: {}", userId, repairOrderDTO.getImageList().size());
            return Result.fail("图片数量不能超过9张");
        }
        
        Long orderId = propertyService.submitRepairOrder(repairOrderDTO);
        return Result.success("报修提交成功", orderId);
    }

    /**
     * 获取我的报修记录
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 使用SecurityUtils.getCurrentUserId()获取当前用户ID
     * - 进行完整的权限验证
     * 
     * @param current 当前页
     * @param size 每页大小
     * @param status 状态筛选
     * @return 分页查询结果
     * @throws Exception 统一异常
     */
    @GetMapping("/mobile/my-orders")
    @Operation(summary = "获取我的报修记录", description = "移动端获取当前用户的报修记录")
    public Result<PageResult<RepairOrderVO>> getMyRepairOrders(
            @Parameter(description = "当前页") @RequestParam(defaultValue = "1") Integer current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "状态筛选") @RequestParam(required = false) Integer status) throws Exception {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("获取我的报修记录失败，用户未登录");
            return Result.fail("用户未登录");
        }
        
        // 分页参数验证
        if (current == null || current < 1) {
            current = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }
        
        PageResult<RepairOrderVO> result = repairOrderService.getMyRepairOrders(current, size, userId, status);
        return Result.success("查询成功", result);
    }

    /**
     * 获取报修详情
     * 
     * 严格按照《Java后端SpringBoot代码开发规范.md》Controller规范：
     * - 异常往外抛：移除try-catch异常处理，添加throws Exception声明
     * - 移除Controller层log.error：避免日志级别错误
     * - 验证用户权限，只能查看自己的报修记录
     * - 增加对工单存在性的验证
     * 
     * @param orderId 工单ID
     * @return 工单详情
     * @throws Exception 统一异常
     */
    @GetMapping("/mobile/{orderId}/detail")
    @Operation(summary = "获取报修详情", description = "移动端获取报修工单详情")
    public Result<RepairOrderVO> getMobileRepairOrderDetail(@Parameter(description = "工单ID") @PathVariable Long orderId) throws Exception {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            log.warn("获取报修详情失败，用户未登录，工单ID: {}", orderId);
            return Result.fail("用户未登录");
        }
        
        // 参数验证
        if (orderId == null) {
            log.warn("获取报修详情失败，工单ID不能为空");
            return Result.fail("工单ID不能为空");
        }
        
        log.info("开始获取报修详情，工单ID: {}, 用户ID: {}", orderId, userId);
        
        RepairOrderVO detail = repairOrderService.getRepairOrderDetail(orderId);
        
        if (detail == null) {
            log.warn("报修详情不存在，工单ID: {}", orderId);
            return Result.fail("报修记录不存在");
        }
        return Result.success("查询成功", detail);
    }
}
